package com.budwk.app.sqfwDoc.codeGenerator.excelGenerate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.budwk.app.sqfw.models.Sqfw_formSummary_new;
import com.budwk.app.sqfw.vo.GenerateExcelUrlVO;
import com.budwk.app.sqfwDoc.bo.ExcelCreateConfig;
import com.budwk.app.sqfwDoc.bo.SqfwExcelForSummaryBO;
import com.budwk.app.sqfwDoc.bo.SqfwExcelJudgeRes;
import com.budwk.app.sqfwDoc.codeGenerator.cusType.SqfwImage;
import com.budwk.app.sqfwDoc.codeGenerator.pdfGenerate.AbstractCustomerPdfCreateField;
import com.budwk.app.util.poiUtils.excelPictureConfigBO.ExcelFileCreateParamBO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.budwk.app.util.poiUtils.CommonFormOfficeUtils.*;

/**
 * @author ZY.Wang
 * @since 2023/12/22
 */
public abstract class BaseTemplateExcelGenerator {

    public GenerateExcelUrlVO createExcel(SqfwExcelCreateCommonBO excelCreateParam) {
        ExcelCreateConfig excelCreateConfig = excelCreateParam.getExcelCreateConfig();

        GenerateExcelUrlVO resultVO = new GenerateExcelUrlVO();

        Map<String, Object> excelParam = new HashMap<>();

        popularSheetBaseParam(excelParam, excelCreateParam);
        customerPopularSheetBaseParam(excelParam, excelCreateParam);

        SqfwExcelJudgeRes sqfwExcelJudgeRes = judgeDataIntoExcelBeforeErgodic(excelCreateParam, excelParam);
        if (sqfwExcelJudgeRes != null) BeanUtil.copyProperties(sqfwExcelJudgeRes, resultVO);
        if (resultVO.getCreateConditionFlag() != null && !resultVO.getCreateConditionFlag()) return resultVO;
        else if (!excelCreateConfig.getCreateExcelFileFlag()) return resultVO;

        List<Map<String, Object>> listMap = Lists.newArrayList();
        popularSheetDataList(listMap, excelCreateParam);
        customerPopularSheetDataParam(listMap, excelCreateParam);

        excelParam.put("list", listMap);

        sqfwExcelJudgeRes = judgeDataIntoExcelBeforeCreate(excelParam);
        if (sqfwExcelJudgeRes != null) BeanUtil.copyProperties(sqfwExcelJudgeRes, resultVO);
        if (resultVO.getCreateConditionFlag() != null && !resultVO.getCreateConditionFlag()) return resultVO;
        else if (!excelCreateConfig.getCreateExcelFileFlag()) return resultVO;

        String templateName = getTemplateName();
        String templatePath = getTemplatePathByOS(templateName);

        String fileName = getDownloadFileName();

        ExcelFileCreateParamBO excelFileCreateParam = new ExcelFileCreateParamBO();
        excelFileCreateParam.setTemplatePath(templatePath);
        excelFileCreateParam.setSheetParam(excelParam);
        excelFileCreateParam.setDataList(listMap);
        excelFileCreateParam.setFileName(fileName);
        excelFileCreateParam.setClazz(getImageConfigBO());
        excelFileCreateParam.setListNotLastRow(!excelCreateConfig.getListAtLastRowFlag());
        excelFileCreateParam.setRowHeight(excelCreateConfig.getRowHeight());
        completeExcelFileCreateParam(excelFileCreateParam);

        resultVO.setCreateConditionFlag(true);
        String url = createExcelAndUpload(excelFileCreateParam);
        resultVO.setExcelUrl(url);
        resultVO.setUrl(url);
        return resultVO;
    }

    /**
     * 框架自动填充一些表头参数
     *
     * @param excelParam       excelMap
     * @param excelCreateParam 创建excel所需的参数
     */
    private void popularSheetBaseParam(Map<String, Object> excelParam, SqfwExcelCreateCommonBO excelCreateParam) {
        BaseExcelParamDTO baseExcelParamDTO = excelCreateParam.getBaseExcelParamDTO();

        excelParam.put("unitName", baseExcelParamDTO.getUnitName());
        excelParam.put("downloadDate", DateUtil.format(baseExcelParamDTO.getDownloadDate(), "yyyy-MM-dd"));
        excelParam.put("createUserName", baseExcelParamDTO.getCreateUserName());
        excelParam.put("province", baseExcelParamDTO.getProvince());
        excelParam.put("city", baseExcelParamDTO.getCity());
        excelParam.put("district", baseExcelParamDTO.getDistrict());
        excelParam.put("county", baseExcelParamDTO.getCounty());
        excelParam.put("community", baseExcelParamDTO.getCommunity());
    }

    /**
     * 框架自动初话一些excel内容数据
     *
     * @param dataList         excel内容区数据
     * @param excelCreateParam 创建excel所提供的数据
     */
    private void popularSheetDataList(List<Map<String, Object>> dataList, SqfwExcelCreateCommonBO excelCreateParam) {
        List<SqfwExcelForSummaryBO> fieldDataList = excelCreateParam.getDataList();

        int rowNum = 0;
        for (SqfwExcelForSummaryBO forSummaryBO : fieldDataList) {

            if (!addRowDataCondition(forSummaryBO)) continue;

            Map<String, Object> rowDataMap = Maps.newHashMap();
            rowDataMap.put("num", ++rowNum);
            Sqfw_formSummary_new sqfwFormSummaryNew = forSummaryBO.getSqfwFormSummaryNew();

            rowDataMap.put("createUserName", sqfwFormSummaryNew.getCreateUserName());
            rowDataMap.put("province", sqfwFormSummaryNew.getProvince());
            rowDataMap.put("city", sqfwFormSummaryNew.getCity());
            rowDataMap.put("district", sqfwFormSummaryNew.getDistrict());
            rowDataMap.put("county", sqfwFormSummaryNew.getCounty());
            rowDataMap.put("community", sqfwFormSummaryNew.getCommunity());

            AbstractCustomerPdfCreateField customerPdfCreateField = forSummaryBO.getCustomerPdfCreateField();
            Class<? extends AbstractCustomerPdfCreateField> fieldDataClass = customerPdfCreateField.getClass();
            Field[] declaredFields = fieldDataClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                declaredField.setAccessible(true);

                String fieldName = declaredField.getName();

                Object fieldValue = getFieldValueByType(declaredField, customerPdfCreateField);

                rowDataMap.put(fieldName, fieldValue);
            }
            customerPopularRowDataMap(rowDataMap, forSummaryBO);
            dataList.add(rowDataMap);
        }
    }

    /**
     * 判断是否添加到数据中的方法
     *
     * @param summaryBO 行数据
     * @return 结果
     */
    protected boolean addRowDataCondition(SqfwExcelForSummaryBO summaryBO) {
        return true;
    }

    /**
     * 填充基础的excel信息，这些信息一般是标题，填报单位，负责人签名，下载时间之类的
     */
    protected abstract void customerPopularSheetBaseParam(Map<String, Object> excelParam, SqfwExcelCreateCommonBO excelCreateParam);

    /**
     * 用户自定义excel字段数据
     */
    protected abstract void customerPopularSheetDataParam(List<Map<String, Object>> listMap, SqfwExcelCreateCommonBO excelCreateParam);

    /**
     * 处理不同类型数据,已经进行了一些初始化了，用户可以自己进行定义
     *
     * @param declaredField 字段
     * @param fieldData     对象
     * @return 结果
     */
    protected Object getFieldValueByType(Field declaredField, AbstractCustomerPdfCreateField fieldData) {

        Object fieldValue = null;

        try {
            fieldValue = declaredField.get(fieldData);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (fieldData == null) {
            return "";
        }

        // 分不同的类型进行处理，如果是字符串的话，可以直接插入数据
        if (String.class.isAssignableFrom(declaredField.getType())) {
            return fieldValue;
        }

        // 如果是时间类型，则使用默认的时间格式进行转化
        if (Date.class.isAssignableFrom(declaredField.getType())) {
            Date fileDate = (Date) fieldValue;

            return DateUtil.format(fileDate, "yyyy-MM-dd");
        }

        // 如果是照片类型则转化为图片
        if (SqfwImage.class.isAssignableFrom(declaredField.getType())) {
            SqfwImage imageData = (SqfwImage) fieldValue;

            List<byte[]> imageByteList = Lists.newArrayList();
            if (imageData == null) return imageByteList;

            List<String> pictureUrlList = imageData.getImageUrlList();
            if (pictureUrlList == null || pictureUrlList.size() == 0) return imageByteList;

            if (pictureUrlList.size() > 2) pictureUrlList = pictureUrlList.subList(0, 2);
            imageByteList = addPictureToByteList(pictureUrlList);

            return imageByteList;
        }

        return fieldValue;
    }

    /**
     * 获取模板名称
     *
     * @return 模板的名称
     */
    protected abstract String getTemplateName();

    /**
     * 获取下载文件的文件
     *
     * @return 下载文件的名称
     */
    public abstract String getDownloadFileName();

    /**
     * 完善excel文件最后需要的一些设置信息
     *
     * @param excelFileCreateParam 已经设置过的一些参数
     */
    protected abstract void completeExcelFileCreateParam(ExcelFileCreateParamBO excelFileCreateParam);

    protected abstract void customerPopularRowDataMap(Map<String, Object> rowDataMap, SqfwExcelForSummaryBO forSummaryBO);

    protected abstract SqfwExcelJudgeRes judgeDataIntoExcelBeforeErgodic(SqfwExcelCreateCommonBO excelCreateParam, Map<String, Object> excelParam);

    protected abstract SqfwExcelJudgeRes judgeDataIntoExcelBeforeCreate(Map<String, Object> excelParam);

    protected abstract Class<?> getImageConfigBO();

    // 主要检查数据是否可以生成
    public List<Sqfw_formSummary_new> generateNewData(List<Sqfw_formSummary_new> summaryList) {
        return summaryList;
    };

}
